import { Injectable } from '@angular/core';
import {Actions, ofType, Effect} from '@ngrx/effects';
import { Observable, of , pipe} from 'rxjs';
import { Router} from '@angular/router';
import { Project} from '../domain';
import * as actions from '../actions/project.action';
import {
      AddAction,
      AddSuccessAction,
      UpdateAction,
      DeleteAction,
      DeleteSuccessAction,
      LoadAction,
      LoadsuccessAction,
      InviteAction,
      InviteSuccessAction,
      SelectProjectAction
    } from '../actions/project.action';
import { Action, Store , select} from '@ngrx/store';
import * as fromRoot from '../reducers';
import * as listActions from '../actions/task-list.action';
import * as userActions from '../actions/user.action';
import { ProjectService } from '../services/project.service';
import {from} from 'rxjs';
import { switchMap, map, catchError , tap, withLatestFrom} from 'rxjs/operators';
@Injectable()
export class ProjectEffects {
    @Effect()
    loadProjects$:Observable<Action> = this.actions$.pipe(
        ofType(actions.ActionTypes.LOAD),
        map((a: LoadAction) => a.payload),
        withLatestFrom(this.store$.pipe(select(fromRoot.getAuthState))),
        switchMap(( [ _, auth]) => {
             return this.projectService.getProjects(auth.user.id).pipe(
                map(projects => {
                    console.log(projects);
                    return new actions.LoadsuccessAction(projects as any)
                }
                    ),
                catchError( err => {
                    console.log(err);
                    return of(new actions.LoadFailAction(JSON.stringify(err)))
                }
                    )
             );
         })
    );
    @Effect()
    addProjects$:Observable<Action> = this.actions$.pipe(
        ofType(actions.ActionTypes.ADD),
        map((a: AddAction) => a.payload),
        withLatestFrom(this.store$.pipe(select(fromRoot.getAuthState), map(auth => auth.user))),
        switchMap(([project, user]) => {
            const added = {...project, members: [`${user.id}`]};
            return this.projectService.add(added).pipe(
                map( pro => new actions.AddSuccessAction(pro)),
                catchError(err => of(new actions.AddFailAction(err)))
            );
           })
    );
    @Effect()
    updateProjects$:Observable<Action> = this.actions$.pipe(
        ofType(actions.ActionTypes.UPDATE),
        map((a: UpdateAction) => a.payload),
        switchMap(project => this.projectService.update(project).pipe(
            map(projects => new actions.UpdateSuccessAction(projects)),
            catchError(err =>  of(new actions.UpdateFailAction(err)))
        ))
    );
    @Effect()
    delProjects$: Observable<Action> = this.actions$.pipe(
        ofType(actions.ActionTypes.DELETE),
        map((a: DeleteAction) => a.payload),
        switchMap(project => this.projectService.del(project)),
        map(projects => new actions.DeleteSuccessAction(projects)),
        catchError(err =>  of(new actions.DeleteFailAction(err)))
    );
    @Effect({dispatch: false})
    selectProject$ = this.actions$.pipe(
        ofType(actions.ActionTypes.SELECT_PROJECT),
        map((a: SelectProjectAction) => a.payload),
        tap((project: Project) => this.router.navigate([`tasklists/${project.id}`]))
    );
    @Effect()
    loadTaskLists$:Observable<Action> = this.actions$.pipe(
        ofType(actions.ActionTypes.SELECT_PROJECT),
        map((a: SelectProjectAction) => a.payload),
        map((project: Project) => new listActions.LoadAction(project.id))
    );
    @Effect()
    invite$:Observable<Action> = this.actions$.pipe(
        ofType(actions.ActionTypes.INVITE),
        map((a: InviteAction) => a.payload),
        switchMap(({projectId, members}) => this.projectService.invite(projectId, members)),
        map(project => new actions.InviteSuccessAction(project)),
        catchError(err =>  of(new actions.InviteFailAction(err)))
    );
    @Effect()
    loadUsers$:Observable<Action> = this.actions$.pipe(
        ofType(actions.ActionTypes.LOAD_SUCCESS),
        map((a: LoadsuccessAction) => a.payload),
        switchMap((projects: Project[]) => from(projects.map(prj => prj.id))),
        map(projectid => new userActions.LoadAction(projectid ))
    );
    @Effect()
    addUserProject$: Observable<Action> = this.actions$.pipe(
        ofType(actions.ActionTypes.ADD_SUCCESS),
        map((a: AddSuccessAction) => a.payload),
        map(project => project.id),
        withLatestFrom(this.store$.pipe(
            select(fromRoot.getAuthState),
            map(auth => auth.user)
        )),
        map(([projectId, user]) => new userActions.AddAction({user: user, projectId: projectId}))
    );
    @Effect()
    removeUserProject$: Observable<Action> = this.actions$.pipe(
        ofType(actions.ActionTypes.DELETE_SUCCESS),
        map((a: DeleteSuccessAction) => a.payload),
        map(project => project.id),
        withLatestFrom(this.store$.pipe(
            select(fromRoot.getAuthState),
            map(auth => auth.user)
        )),
        map(([projectId, user]) => new userActions.DeleteAction({user: user, projectId: projectId}))
    );
    @Effect()
    updateUserProject$:Observable<Action> = this.actions$.pipe(
        ofType(actions.ActionTypes.INVITE_SUCCESS),
        map((a: InviteSuccessAction) => a.payload),
        map(project => new userActions.UpdateAction(project))
    );
    constructor(
        public actions$: Actions,
        public projectService: ProjectService,
        public store$: Store<fromRoot.State>,
        public router: Router
               ) {}
}
